package com.cehome.cloudbox.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpStatus;
import cn.hutool.json.JSONUtil;
import com.cehome.cloudbox.base.R;
import com.cehome.cloudbox.constans.ExtensionTaskProperties;
import com.cehome.cloudbox.doman.dto.*;
import com.cehome.cloudbox.service.IProcCommonService;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.task.Comment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * <p>
 * Flowable共通 服务实现类
 * </p>
 */
@Service
@Slf4j
public class ProcCommonServiceImpl implements IProcCommonService {
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private HttpServletRequest request;

    @Override
    public List<String> getUserIdList(String data, String applyUserId) {
        return null;
    }

    /**
     * 添加任务处理意见
     *
     * @param taskId      任务ID
     * @param procIncId   流程实例ID
     * @param commentType 意见类型
     * @param message     意见消息
     * @param userId      用户ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addTaskHandleComment(String taskId, String procIncId, String commentType, String message, String userId) {
        // 在变量中设置流程任务说明类型
        taskService.setVariable(taskId, ExtensionTaskProperties.FLOWABLE_PROCESS_TASK_COMMENT_TYPE, commentType);
        // 添加说明
        Comment comment = taskService.addComment(
                taskId,
                procIncId,
                commentType,
                ObjectUtil.isEmpty(message) ? StrUtil.EMPTY : message);
        // 更新说明中的用户ID
        comment.setUserId(userId);
        taskService.saveComment(comment);
    }

    /**
     * 获取流程实例状态
     *
     * @param procInsId 流程实例ID
     * @return 流程实例状态
     */
    @Override
    public ProcStateDto procIncState(String procInsId) {
        ProcStateDto procStateDto = new ProcStateDto();
        // 查看流程实例是否完成
        HistoricProcessInstance hisProcIns = historyService.createHistoricProcessInstanceQuery()
                .includeProcessVariables()
                .processInstanceId(procInsId)
                .singleResult();

        if (ObjectUtil.isEmpty(hisProcIns) || StrUtil.isEmpty(hisProcIns.getId())) {
            return procStateDto;
        }

        procStateDto.setProcInsId(procInsId);
        // 流程状态
        procStateDto.setProcInsState(
                Convert.toStr(hisProcIns.getProcessVariables().get(ExtensionTaskProperties.FLOWABLE_PROCESS_INSTANCE_STATE)));
        return procStateDto;
    }

    /**
     * 业务回调方法
     *
     * @param paramDto     请求参数
     * @param baseUrl      基准URL
     * @param relativePath 相对URL
     */
    @Override
    public void callBack(ProcCallBackParamDto paramDto, String baseUrl, String relativePath) {

        // 设置请求头
        Map<String, String> headerMap = new HashMap<>();
        Enumeration<String> enumeration = request.getHeaderNames();
        while (enumeration.hasMoreElements()) {
            String name = enumeration.nextElement();
            headerMap.put(name, request.getHeader(name));
        }

        // 调用回调地址
        String url = URLUtil.completeUrl(baseUrl, relativePath);
        HttpResponse response = HttpRequest.post(url)
                .headerMap(headerMap, false)
                .body(JSONUtil.toJsonStr(paramDto))
                .timeout(30000)
                .execute();

        if (HttpStatus.HTTP_OK != response.getStatus()) {
            log.error("调用回调地址失败，回调地址：{}", url);

        }
        R result = JSONUtil.toBean(response.body(), R.class);

    }

    @Override
    public String createProcSerialNoByProcCode(String procCode) {
        return null;
    }
}
